Loading and matching test and retest datasets

Load original data

test_data <- read.csv('/Users/zeynepenkavi/Documents/PoldrackLabLocal/Self_Regulation_Ontology/Data/Complete_01-31-2017/variables_exhaustive.csv')

Load retest data

retest_data <- read.csv('/Users/zeynepenkavi/Documents/PoldrackLabLocal/Self_Regulation_Ontology/Data/Retest_02-11-2017/variables_exhaustive.csv')

Function to process lookup table

process_lookup <- function(lookup_json){
  lookup_json <- data.frame(unlist(lookup_json))
  lookup_json$sub_id <- as.character(row.names(lookup_json))
  row.names(lookup_json) <- seq(1:nrow(lookup_json))
  names(lookup_json)[1] <- 'worker_id'
  lookup_json$worker_id <- as.character(lookup_json$worker_id)
  lookup_json$complete <- ifelse(lookup_json$worker_id == lookup_json$sub_id, 0, 1)
  lookup_json <- lookup_json %>% arrange(-complete, sub_id)
  return(lookup_json)
}

Extract retest participants from test data

test_worker_lookup <- fromJSON('/Users/zeynepenkavi/Documents/PoldrackLabLocal/Self_Regulation_Ontology/Data/Retest_02-11-2017/Local/worker_lookup.json')
#Process full lookup tables for both datasets
test_worker_lookup <- process_lookup(test_worker_lookup)
#Process sub_id columns in the data dataframes
retest_data$X <- as.character(retest_data$X)
test_data$X <- as.character(test_data$X)
names(retest_data)[1] <- 'sub_id'
names(test_data)[1] <- 'sub_id'
#Trim lookup table to only include those we have data for
test_worker_lookup <- test_worker_lookup[test_worker_lookup$sub_id %in% test_data$sub_id,]
#Replace worker_id's in retest_data with original sub_id's 
correct_subids <- function(row, lookup_table){
  sub_id = row$sub_id
  if(sub_id %in% lookup_table$worker_id){
    index = which(sub_id == lookup_table$worker_id)
    sub_id = lookup_table$sub_id[index]
    row$sub_id = sub_id
  }
  return(row)
}
retest_data <- retest_data %>%
  group_by(sub_id) %>%
  do(correct_subids(.,test_worker_lookup))

Are all retest subjects in test_data? No.

sum(retest_data$sub_id %in% test_data$sub_id) == nrow(retest_data)
[1] FALSE

Who is missing?

retest_data$sub_id[which(retest_data$sub_id %in% test_data$sub_id == FALSE)]
[1] "s442"

One retest participant is not in test data. Remove that subject from retest_data for now

retest_data <- retest_data[retest_data$sub_id %in% test_data$sub_id,]
retest_data

Extract test data for retest subjects

retest_subs_test_data <- test_data[test_data$sub_id %in% retest_data$sub_id,]
rest_subs_test_data <- test_data[test_data$sub_id %in% retest_data$sub_id == FALSE,]
#Arrange datasets of same size by sub_id
retest_data = retest_data %>% arrange(sub_id)
retest_subs_test_data = retest_subs_test_data %>% arrange(sub_id)
#CHECK IF EVERYTHING IS ORDERED RIGHT
retest_subs_test_data$sub_id == retest_data$sub_id
  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 [16] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 [31] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 [46] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 [61] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 [76] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 [91] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[106] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[121] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[136] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE

Drop columns from original data that are not in retest data

Are there any columns in retest data columns that are not in the original data: No.

names(retest_data)[names(retest_data) %in% names(retest_subs_test_data) == FALSE]
character(0)

Test data columns that are not in the retest data: Two stage hasn’t been fixed yet.

names(retest_subs_test_data)[names(retest_subs_test_data) %in% names(retest_data) == FALSE]
[1] "two_stage_decision.perseverance"

Datasets with only matching columns

all_columns <- unique(c(names(retest_data), names(retest_subs_test_data)))
matching_columns <- c()
for(i in 1:length(all_columns)){
  if(all_columns[i] %in% names(retest_data) & all_columns[i] %in% names(retest_subs_test_data)){
    matching_columns <- c(matching_columns, all_columns[i])
  }
}
retest_data <- retest_data[,matching_columns]
retest_subs_test_data <- retest_subs_test_data[,matching_columns]

Correlations of exhaustive variables

Get list of test retest correlations for all matching (numeric) columns in the test and retest data. Note two caveats: 1. There are still some columns that weren’t in both datasets (e.g. two stage) 2. Unlike meaningful variables these variables are not (yet) rid of outliers or log transformed if skewed. This will be detailed below along with its problems.

retest_data <- as.data.frame(retest_data)
retest_subs_test_data <- as.data.frame(retest_subs_test_data)
matching_dv_columns <- c()
for(i in 1:length(matching_columns)){
  if(is.numeric(retest_data[,matching_columns[i]]) & is.numeric(retest_subs_test_data[,matching_columns[i]])){
    matching_dv_columns <- c(matching_dv_columns, matching_columns[i])
  }
}
cor_df <- data.frame(pearson = rep(NA, length(matching_dv_columns)), spearman = rep(NA, length(matching_dv_columns)))
row.names(cor_df) <- matching_dv_columns
for(i in 1:length(matching_dv_columns)){
  cor_df[matching_dv_columns[i], 'pearson'] <- cor(retest_data[,matching_dv_columns[i]], retest_subs_test_data[,matching_dv_columns[i]], method = 'pearson', use = "pairwise.complete.obs")
  cor_df[matching_dv_columns[i], 'spearman'] <- cor(retest_data[,matching_dv_columns[i]],retest_subs_test_data[,matching_dv_columns[i]], method = 'spearman', use = "pairwise.complete.obs")
}

Distribution of all Pearson and Spearman correlations

Add column to tasks vs. surveys in correlation table

cor_df$dv = row.names(cor_df)
row.names(cor_df) = seq(1:nrow(cor_df))
cor_df$task = 'task'
cor_df[grep('survey', cor_df$dv), 'task'] = 'survey'

Distributions of correlations by task vs. survey

Survey reliabilities are noticably higher than task reliabilities.

Task reliability distributions looks alsmost bimodal. Should figure out whether the lower ones are specific tasks or if they are certain kinds of vars (e.g. certain ddm parameters)

cor_df %>%
  gather(key, value, -dv, -task) %>%
  ggplot(aes(value))+
  geom_histogram()+
  theme_bw()+
  facet_wrap(key~task)

Rank order correlations For tasks

cor_df %>%
  filter(task == 'task') %>%
  select(dv, spearman, pearson) %>%
  arrange(-pearson, -spearman)

Mean reliability for tasks

For surveys

Note: Holt and Laury test-retest is pretty terrible. In previous data it was ~.35. Should check to see if there is a coding error there.

cor_df %>%
  filter(task == 'survey') %>%
  select(dv, spearman, pearson) %>%
  arrange(-pearson, -spearman)

Mean reliability for surveys

Distribution of each variable

Check if the variables that went in to the correlation matrix have normal distributions since at least the Pearson correlations depend on this assumption. If not transform data columns in both retest and test data and calculate a new correlation df.

Function to check if the variables that went in to cor_df have normal distributions

diff_from_normal <- function(col){
  return(shapiro.test(col)$p.value < 0.05)
}

Check distributions of retest data

The smaller meaningful vars dataframe have been somewhat cleaned. So far in this notebook we looked at all the vars in their rawest form. Here we’ll first check the distributions of all the variables and then apply the same cleaning procedure that was used for the meaningful variables to all of them.

Note that I’m doing this for the sake of consistency for now. We might later decide that we would like to transform certain variables of interest in other ways to be able to include them in our analyses without violating the assumptions of those analyses. The current procedure checks the skewness of a column

Create and organize new df where distribution of vars data is stored. First for retest data only; then for test data for subjects who have retest data - restricting here since these are the subsets of data that went in to the correlation matrix. Merge and cleanup

dist_retest_data <- as.data.frame(apply(retest_data[,matching_dv_columns], 2, diff_from_normal))
names(dist_retest_data) <- c('retest_not_normal')
dist_retest_data$dv <- row.names(dist_retest_data)
row.names(dist_retest_data) <- seq(1:nrow(dist_retest_data))
dist_retest_data = dist_retest_data %>% select(dv, retest_not_normal)
dist_retest_subs_test_data <- as.data.frame(apply(retest_subs_test_data[,matching_dv_columns], 2, diff_from_normal))
names(dist_retest_subs_test_data) <- c('test_not_normal')
dist_retest_subs_test_data$dv <- row.names(dist_retest_subs_test_data)
row.names(dist_retest_subs_test_data) <- seq(1:nrow(dist_retest_subs_test_data))
dist_retest_subs_test_data = dist_retest_subs_test_data %>% select(dv, test_not_normal)
dist_data <- merge(dist_retest_data, dist_retest_subs_test_data, by = 'dv')
rm(dist_retest_data, dist_retest_subs_test_data)

Add whether dv’s are tasks or survey to distribution dfs

cor_df %>%
  select(dv, task) %>%
  left_join(dist_data, by = 'dv')

What proportion is not normal? A large proportion of the variables are not normal for data from both sources. Larger proportions of survey data are not normal compared to task data.

Are the same vars that are not normally distributed in the retest data not normal in test data as well? List of variables that have different distributions in the two time points (shown here is whether they are normally distributed in the retest data) A majority of them are drift diffusion parameters (but note that these vars are overrepresented to begin with - more on them later).

Apply the same cleaning procedure that was used for meaningful vars for all vars:

transform_remove_skew = function(data, columns, threshold = 1){
  
  tmp = as.data.frame(apply(data[,columns],2,skew))
  names(tmp) = c("skew")
  tmp$dv = row.names(tmp)
  tmp = tmp %>% 
    filter(abs(skew)>threshold)
  
  skewed_variables = tmp$dv
  skew_subset = data[, skewed_variables]
  positive_subset = data[,tmp$dv[tmp$skew>0]]
  negative_subset = data[,tmp$dv[tmp$skew<0]]
  
  # transform variables
  # log transform for positive skew
  positive_subset = log(positive_subset)
  successful_transforms = as.data.frame(apply(positive_subset, 2, skew))
  names(successful_transforms) = c('skew')
  successful_transforms$dv = row.names(successful_transforms)
  successful_transforms = successful_transforms %>% filter(abs(skew)<threshold)
  successful_transforms = successful_transforms$dv
  successful_transforms = positive_subset[,successful_transforms]
  dropped_vars = names(positive_subset) %w/o% names(successful_transforms)
  
  # replace transformed variables
  data = data[,-c(which(names(data) %in% names(positive_subset)))]
  names(successful_transforms) = paste0(names(successful_transforms), '.logTr')
  print.noquote(rep('*', 40))
  print(paste0('Dropping ', length(dropped_vars) ,' positively skewed data that could not be transformed successfully:'))
  print(dropped_vars)
  print.noquote(rep('*', 40))
  data = cbind(data, successful_transforms)
  
  # reflected log transform for negative skew      
  negative_subset = as.data.frame(apply(negative_subset, 2, neg_log))
  successful_transforms = as.data.frame(apply(negative_subset, 2, skew))
  names(successful_transforms) = c('skew')
  successful_transforms$dv = row.names(successful_transforms)
  successful_transforms = successful_transforms %>% filter(abs(skew)<1)
  successful_transforms = successful_transforms$dv
  successful_transforms = negative_subset[,successful_transforms]
  dropped_vars = names(negative_subset) %w/o% names(successful_transforms)
  
  # replace transformed variables
  data = data[,-c(which(names(data) %in% names(negative_subset)))]
  names(successful_transforms) = paste0(names(successful_transforms), '.ReflogTr')
  print.noquote(rep('*', 40))
  print(paste0('Dropping ', length(dropped_vars) ,' negatively skewed data that could not be transformed successfully:'))
  print(dropped_vars)
  print.noquote(rep('*', 40))
  data = cbind(data, successful_transforms)
  
  return(data)
}
transform_remove_skew(retest_data, matching_dv_columns)
NaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs produced
 [1] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
[1] "Dropping 39 positively skewed data that could not be transformed successfully:"
 [1] "adaptive_n_back.missed_percent"                            
 [2] "attention_network_task.avg_rt_error"                       
 [3] "attention_network_task.missed_percent"                     
 [4] "bickel_titrator.hyp_discount_rate_large"                   
 [5] "choice_reaction_time.avg_rt_error"                         
 [6] "choice_reaction_time.missed_percent"                       
 [7] "choice_reaction_time.std_rt_error"                         
 [8] "demographics_survey.arrest_count"                          
 [9] "demographics_survey.caffeine_intake"                       
[10] "demographics_survey.car_debt"                              
[11] "demographics_survey.divoce_count"                          
[12] "demographics_survey.longest_relationship.months."          
[13] "demographics_survey.mortage_debt"                          
[14] "demographics_survey.other_sources_of_debt"                 
[15] "demographics_survey.traffic_ticket_count"                  
[16] "dickman_survey.dysfunctional"                              
[17] "dietary_decision.health_sensitivity"                       
[18] "directed_forgetting.missed_percent"                        
[19] "discount_titrate.hyp_discount_rate_nm"                     
[20] "dot_pattern_expectancy.EZ_non_decision_BX"                 
[21] "dot_pattern_expectancy.missed_percent"                     
[22] "hierarchical_rule.missed_percent"                          
[23] "holt_laury_survey.number_of_switches"                      
[24] "impulsive_venture_survey.impulsiveness"                    
[25] "local_global_letter.missed_percent"                        
[26] "local_global_letter.std_rt_error"                          
[27] "probabilistic_selection.missed_percent"                    
[28] "psychological_refractory_period_two_choices.missed_percent"
[29] "recent_probes.missed_percent"                              
[30] "shape_matching.missed_percent"                             
[31] "shift_task.missed_percent"                                 
[32] "simon.missed_percent"                                      
[33] "simple_reaction_time.missed_percent"                       
[34] "stop_signal.proactive_SSRT_speeding"                       
[35] "stroop.missed_percent"                                     
[36] "stroop.post_error_slowing"                                 
[37] "threebytwo.cue_switch_cost_rt_100.0"                       
[38] "threebytwo.missed_percent"                                 
[39] "two_stage_decision.missed_percent"                         
 [1] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 [1] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
[1] "Dropping 35 negatively skewed data that could not be transformed successfully:"
 [1] "attention_network_task.acc"                           
 [2] "attention_network_task.conflict_acc"                  
 [3] "attention_network_task.orienting_acc"                 
 [4] "choice_reaction_time.acc"                             
 [5] "columbia_card_task_cold.loss_sensitivity"             
 [6] "directed_forgetting.acc"                              
 [7] "discount_titrate.hyp_discount_rate_glm"               
 [8] "discount_titrate.hyp_discount_rate_glm_notnow"        
 [9] "discount_titrate.hyp_discount_rate_glm_now"           
[10] "dot_pattern_expectancy.AY.BY_acc"                     
[11] "dot_pattern_expectancy.BX.BY_EZ_drift"                
[12] "dot_pattern_expectancy.BX.BY_acc"                     
[13] "dot_pattern_expectancy.BX.BY_rt"                      
[14] "dot_pattern_expectancy.acc"                           
[15] "go_nogo.acc"                                          
[16] "go_nogo.go_acc"                                       
[17] "information_sampling_task.Fixed_Win_acc"              
[18] "local_global_letter.acc"                              
[19] "motor_selective_stop_signal.go_acc"                   
[20] "motor_selective_stop_signal.stop_acc"                 
[21] "psychological_refractory_period_two_choices.task1_acc"
[22] "psychological_refractory_period_two_choices.task2_acc"
[23] "recent_probes.acc"                                    
[24] "shape_matching.EZ_non_decision_SSS"                   
[25] "shape_matching.acc"                                   
[26] "shape_matching.hddm_non_decision"                     
[27] "simon.acc"                                            
[28] "simon.hddm_non_decision"                              
[29] "stim_selective_stop_signal.go_acc"                    
[30] "stim_selective_stop_signal.stop_acc"                  
[31] "stop_signal.go_acc"                                   
[32] "stop_signal.stop_acc"                                 
[33] "stroop.acc"                                           
[34] "stroop.stroop_acc"                                    
[35] "threebytwo.acc"                                       
 [1] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
clean_retest_data = transform_remove_skew(clean_retest_data, matching_dv_columns)
NaNs produced
 [1] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
[39] * *
[1] "Dropping 18 positively skewed data that could not be transformed successfully:"
 [1] "adaptive_n_back.missed_percent"                            
 [2] "attention_network_task.missed_percent"                     
 [3] "bickel_titrator.hyp_discount_rate_small"                   
 [4] "demographics_survey.caffeine_intake"                       
 [5] "demographics_survey.car_debt"                              
 [6] "demographics_survey.mortage_debt"                          
 [7] "directed_forgetting.missed_percent"                        
 [8] "dot_pattern_expectancy.missed_percent"                     
 [9] "hierarchical_rule.missed_percent"                          
[10] "impulsive_venture_survey.impulsiveness"                    
[11] "local_global_letter.missed_percent"                        
[12] "probabilistic_selection.missed_percent"                    
[13] "psychological_refractory_period_two_choices.missed_percent"
[14] "shape_matching.missed_percent"                             
[15] "shift_task.missed_percent"                                 
[16] "stroop.missed_percent"                                     
[17] "threebytwo.missed_percent"                                 
[18] "two_stage_decision.missed_percent"                         
 [1] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
[39] * *
 [1] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
[39] * *
[1] "Dropping 7 negatively skewed data that could not be transformed successfully:"
[1] "attention_network_task.acc"                           
[2] "choice_reaction_time.acc"                             
[3] "directed_forgetting.acc"                              
[4] "go_nogo.go_acc"                                       
[5] "motor_selective_stop_signal.stop_acc"                 
[6] "psychological_refractory_period_two_choices.task1_acc"
[7] "psychological_refractory_period_two_choices.task2_acc"
 [1] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
[39] * *

I’m not sure what is the right thing to do regarding the cleaning of the test data for the retest subjects. Should they be cleaned on the whole sample for the time they were collected on and then extracted (this should have an effect on outliers as well as transformations) or extracted and then cleaned. Here I am doing the latter but this seems to be resulting in more skewed variables.

clean_retest_subs_test_data = transform_remove_skew(retest_subs_test_data, matching_dv_columns)
NaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs producedNaNs produced
 [1] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
[39] * *
[1] "Dropping 42 positively skewed data that could not be transformed successfully:"
 [1] "adaptive_n_back.missed_percent"                            
 [2] "adaptive_n_back.std_rt"                                    
 [3] "attention_network_task.avg_rt_error"                       
 [4] "attention_network_task.missed_percent"                     
 [5] "choice_reaction_time.missed_percent"                       
 [6] "choice_reaction_time.std_rt_error"                         
 [7] "columbia_card_task_cold.gain_sensitivity"                  
 [8] "demographics_survey.arrest_count"                          
 [9] "demographics_survey.caffeine_intake"                       
[10] "demographics_survey.car_debt"                              
[11] "demographics_survey.divoce_count"                          
[12] "demographics_survey.household_income.dollars."             
[13] "demographics_survey.longest_relationship.months."          
[14] "demographics_survey.mortage_debt"                          
[15] "demographics_survey.other_sources_of_debt"                 
[16] "demographics_survey.percent_retirement_in_stock"           
[17] "demographics_survey.traffic_ticket_count"                  
[18] "dickman_survey.dysfunctional"                              
[19] "directed_forgetting.missed_percent"                        
[20] "directed_forgetting.proactive_interference_acc"            
[21] "dot_pattern_expectancy.missed_percent"                     
[22] "dot_pattern_expectancy.std_rt"                             
[23] "dot_pattern_expectancy.std_rt_error"                       
[24] "hierarchical_rule.missed_percent"                          
[25] "holt_laury_survey.number_of_switches"                      
[26] "impulsive_venture_survey.impulsiveness"                    
[27] "local_global_letter.missed_percent"                        
[28] "local_global_letter.switch_cost_rt"                        
[29] "probabilistic_selection.missed_percent"                    
[30] "psychological_refractory_period_two_choices.missed_percent"
[31] "recent_probes.missed_percent"                              
[32] "shape_matching.missed_percent"                             
[33] "shift_task.missed_percent"                                 
[34] "simon.missed_percent"                                      
[35] "simple_reaction_time.missed_percent"                       
[36] "stim_selective_stop_signal.go_rt_std"                      
[37] "stim_selective_stop_signal.stop_rt_error_std"              
[38] "stroop.missed_percent"                                     
[39] "threebytwo.cue_switch_cost_rt_100.0"                       
[40] "threebytwo.missed_percent"                                 
[41] "threebytwo.task_inhibition_900.0"                          
[42] "two_stage_decision.missed_percent"                         
 [1] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
[39] * *
 [1] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
[39] * *
[1] "Dropping 37 negatively skewed data that could not be transformed successfully:"
 [1] "adaptive_n_back.acc"                                  
 [2] "attention_network_task.acc"                           
 [3] "attention_network_task.conflict_acc"                  
 [4] "attention_network_task.hddm_non_decision"             
 [5] "choice_reaction_time.acc"                             
 [6] "columbia_card_task_cold.loss_sensitivity"             
 [7] "columbia_card_task_hot.loss_sensitivity"              
 [8] "directed_forgetting.acc"                              
 [9] "directed_forgetting.proactive_interference_rt"        
[10] "dot_pattern_expectancy.BX.BY_acc"                     
[11] "dot_pattern_expectancy.BX.BY_rt"                      
[12] "dot_pattern_expectancy.EZ_non_decision_AX"            
[13] "dot_pattern_expectancy.acc"                           
[14] "go_nogo.acc"                                          
[15] "go_nogo.go_acc"                                       
[16] "hierarchical_rule.post_error_slowing"                 
[17] "information_sampling_task.Fixed_Win_acc"              
[18] "motor_selective_stop_signal.go_acc"                   
[19] "motor_selective_stop_signal.stop_acc"                 
[20] "probabilistic_selection.positive_learning_bias"       
[21] "psychological_refractory_period_two_choices.task1_acc"
[22] "psychological_refractory_period_two_choices.task2_acc"
[23] "recent_probes.acc"                                    
[24] "shape_matching.acc"                                   
[25] "shape_matching.hddm_non_decision"                     
[26] "simon.acc"                                            
[27] "simon.post_error_slowing"                             
[28] "simon.simon_acc"                                      
[29] "stim_selective_stop_signal.EZ_non_decision"           
[30] "stim_selective_stop_signal.go_acc"                    
[31] "stim_selective_stop_signal.hddm_non_decision"         
[32] "stop_signal.go_acc"                                   
[33] "stop_signal.go_rt_error"                              
[34] "stop_signal.hddm_non_decision"                        
[35] "stroop.acc"                                           
[36] "stroop.stroop_acc"                                    
[37] "threebytwo.acc"                                       
 [1] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
[39] * *

But what about dropping different variables from the two dataframes

Drift diffusion variables: raw vars vs. EZ vs. hddm

Mean reliabilities for different kinds of variables (e.g. drift rates and NDs; separately for EZ and HDDM; subtraction vs basic variables - single vs. multiple)


Can you get the factor structure for the retest step 1:Ttest on all measures of T1 for people w and without retest

step2 : efa on the people you don’t have retest on and then predict how well this holds up for people w retest on t1 and on t2

Data cleaning for efa

#read in only meaningful vars
meaningful_var_test <- read.csv('/Users/zeynepenkavi/Documents/PoldrackLabLocal/Self_Regulation_Ontology/Data/Complete_01-31-2017/meaningful_variables_clean.csv')

meaningful_var_retest <- read.csv('/Users/zeynepenkavi/Documents/PoldrackLabLocal/Self_Regulation_Ontology/Data/Retest_02-11-2017/meaningful_variables_clean.csv')

#Process sub_id columns in the data dataframes
meaningful_var_retest$X <- as.character(meaningful_var_retest$X)
meaningful_var_test$X <- as.character(meaningful_var_test$X)

names(meaningful_var_retest)[1] <- 'sub_id'
names(meaningful_var_test)[1] <- 'sub_id'

#Clean and subset dfs as before
meaningful_var_retest <- meaningful_var_retest %>%
  group_by(sub_id) %>%
  do(correct_subids(.,test_worker_lookup))

#Are all retest subjects in test_data? No. 
sum(meaningful_var_retest$sub_id %in% meaningful_var_test$sub_id) == nrow(meaningful_var_retest)

#Who is missing?
meaningful_var_retest$sub_id[which(meaningful_var_retest$sub_id %in% meaningful_var_test$sub_id == FALSE)]

#Remove sub w missing test data from retest data
retest_data_mngf <- meaningful_var_retest[meaningful_var_retest$sub_id %in% meaningful_var_test$sub_id,]

#Extract test data for subs w retest data
retest_subs_test_mngf <- meaningful_var_test[meaningful_var_test$sub_id %in% meaningful_var_retest$sub_id,]

#Extract test data for subs without retest data (efa df)
rest_subs_test_mngf <- meaningful_var_test[meaningful_var_test$sub_id %in% meaningful_var_retest$sub_id == FALSE,]

#Arrange datasets of same size by sub_id
retest_data_mngf = retest_data_mngf %>% arrange(sub_id)
retest_subs_test_mngf = retest_subs_test_mngf %>% arrange(sub_id)

#CHECK IF EVERYTHING IS ORDERED RIGHT
retest_subs_test_mngf$sub_id == retest_data_mngf$sub_id

Checking columns for efa: NEED TO RESOLVE SOME DIFFERENCES IN MEANINGFUL VARS BETWEEN THE TWO DATASETS

#Check columns 
names(retest_data_mngf)[names(retest_data_mngf) %in% names(retest_subs_test_mngf) == FALSE]

names(retest_subs_test_mngf)[names(retest_subs_test_mngf) %in% names(retest_data_mngf) == FALSE]

#Subset datasets with only matching columns
all_columns_mngf <- unique(c(names(retest_data_mngf), names(retest_subs_test_mngf)))

matching_columns_mngf <- c()
for(i in 1:length(all_columns_mngf)){
  if(all_columns_mngf[i] %in% names(retest_data_mngf) & all_columns_mngf[i] %in% names(retest_subs_test_mngf)){
    matching_columns_mngf <- c(matching_columns_mngf, all_columns_mngf[i])
  }
}

retest_data_mngf <- retest_data_mngf[,matching_columns_mngf]
retest_subs_test_mngf <- retest_subs_test_mngf[,matching_columns_mngf]
rest_subs_test_mngf <- rest_subs_test_mngf[,matching_columns_mngf]

#standardize all vars going in to factor analysis
rest_subs_test_mngf_z <- rest_subs_test_mngf

for(i in 1:length(rest_subs_test_mngf)){
  if(names(rest_subs_test_mngf)[i] == 'sub_id'){
    rest_subs_test_mngf_z$sub_id = rest_subs_test_mngf$sub_id
  }
  else{
    rest_subs_test_mngf_z[,names(rest_subs_test_mngf)[i]] = scale(rest_subs_test_mngf[,i])
  }
}

rest_subs_test_mngf_z <- as.data.frame(rest_subs_test_mngf_z)

Efa on subjects from original dataset withOUT retest data (using meaningful vars only)

unrotated <- efaUnrotate(rest_subs_test_mngf_z, nf=3, varList=names(rest_subs_test_mngf_z)[-1], estimator="mlr")

summary(unrotated, std=TRUE)
inspect(unrotated, "std")
corMat <- rest_subs_test_mngf_z %>% select(-sub_id) %>% cor(.,use = 'complete.obs')

solution <- fa(r = corMat, nfactors = 3, rotate = "oblimin", fm = "pa")
solution

Completion times/days

T1 comparison for people who came back vs didn’t (of all that are invited)

LS0tCnRpdGxlOiAnU2VsZiBSZWd1bGF0aW9uIE9udG9sb2d5IFJldGVzdCBEYXRhOiBJbml0aWFsIEV4cGxvcmF0aW9uJwpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMgogICAgdG9jX2Zsb2F0OiB0cnVlCi0tLQoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkobG1lNCkKbGlicmFyeShHR2FsbHkpCmxpYnJhcnkoanNvbmxpdGUpCmxpYnJhcnkobGF2YWFuKQpsaWJyYXJ5KHNlbVRvb2xzKQpsaWJyYXJ5KHBzeWNoKQpsaWJyYXJ5KEdQQXJvdGF0aW9uKQpzZW0gPC0gZnVuY3Rpb24oeCkge3NkKHgpIC8gc3FydChsZW5ndGgoeCkpfQpvcHRpb25zKGRpZ2l0cyA9IDQpCmBgYAoKIyBMb2FkaW5nIGFuZCBtYXRjaGluZyB0ZXN0IGFuZCByZXRlc3QgZGF0YXNldHMKCkxvYWQgb3JpZ2luYWwgZGF0YQpgYGB7cn0KdGVzdF9kYXRhIDwtIHJlYWQuY3N2KCcvVXNlcnMvemV5bmVwZW5rYXZpL0RvY3VtZW50cy9Qb2xkcmFja0xhYkxvY2FsL1NlbGZfUmVndWxhdGlvbl9PbnRvbG9neS9EYXRhL0NvbXBsZXRlXzAxLTMxLTIwMTcvdmFyaWFibGVzX2V4aGF1c3RpdmUuY3N2JykKYGBgCgpMb2FkIHJldGVzdCBkYXRhCmBgYHtyfQpyZXRlc3RfZGF0YSA8LSByZWFkLmNzdignL1VzZXJzL3pleW5lcGVua2F2aS9Eb2N1bWVudHMvUG9sZHJhY2tMYWJMb2NhbC9TZWxmX1JlZ3VsYXRpb25fT250b2xvZ3kvRGF0YS9SZXRlc3RfMDItMTEtMjAxNy92YXJpYWJsZXNfZXhoYXVzdGl2ZS5jc3YnKQpgYGAKCkZ1bmN0aW9uIHRvIHByb2Nlc3MgbG9va3VwIHRhYmxlCmBgYHtyfQpwcm9jZXNzX2xvb2t1cCA8LSBmdW5jdGlvbihsb29rdXBfanNvbil7CiAgbG9va3VwX2pzb24gPC0gZGF0YS5mcmFtZSh1bmxpc3QobG9va3VwX2pzb24pKQogIGxvb2t1cF9qc29uJHN1Yl9pZCA8LSBhcy5jaGFyYWN0ZXIocm93Lm5hbWVzKGxvb2t1cF9qc29uKSkKICByb3cubmFtZXMobG9va3VwX2pzb24pIDwtIHNlcSgxOm5yb3cobG9va3VwX2pzb24pKQogIG5hbWVzKGxvb2t1cF9qc29uKVsxXSA8LSAnd29ya2VyX2lkJwogIGxvb2t1cF9qc29uJHdvcmtlcl9pZCA8LSBhcy5jaGFyYWN0ZXIobG9va3VwX2pzb24kd29ya2VyX2lkKQogIGxvb2t1cF9qc29uJGNvbXBsZXRlIDwtIGlmZWxzZShsb29rdXBfanNvbiR3b3JrZXJfaWQgPT0gbG9va3VwX2pzb24kc3ViX2lkLCAwLCAxKQogIGxvb2t1cF9qc29uIDwtIGxvb2t1cF9qc29uICU+JSBhcnJhbmdlKC1jb21wbGV0ZSwgc3ViX2lkKQogIHJldHVybihsb29rdXBfanNvbikKfQpgYGAKCkV4dHJhY3QgcmV0ZXN0IHBhcnRpY2lwYW50cyBmcm9tIHRlc3QgZGF0YQoKYGBge3J9CnRlc3Rfd29ya2VyX2xvb2t1cCA8LSBmcm9tSlNPTignL1VzZXJzL3pleW5lcGVua2F2aS9Eb2N1bWVudHMvUG9sZHJhY2tMYWJMb2NhbC9TZWxmX1JlZ3VsYXRpb25fT250b2xvZ3kvRGF0YS9SZXRlc3RfMDItMTEtMjAxNy9Mb2NhbC93b3JrZXJfbG9va3VwLmpzb24nKQoKI1Byb2Nlc3MgZnVsbCBsb29rdXAgdGFibGVzIGZvciBib3RoIGRhdGFzZXRzCnRlc3Rfd29ya2VyX2xvb2t1cCA8LSBwcm9jZXNzX2xvb2t1cCh0ZXN0X3dvcmtlcl9sb29rdXApCgojUHJvY2VzcyBzdWJfaWQgY29sdW1ucyBpbiB0aGUgZGF0YSBkYXRhZnJhbWVzCnJldGVzdF9kYXRhJFggPC0gYXMuY2hhcmFjdGVyKHJldGVzdF9kYXRhJFgpCnRlc3RfZGF0YSRYIDwtIGFzLmNoYXJhY3Rlcih0ZXN0X2RhdGEkWCkKCm5hbWVzKHJldGVzdF9kYXRhKVsxXSA8LSAnc3ViX2lkJwpuYW1lcyh0ZXN0X2RhdGEpWzFdIDwtICdzdWJfaWQnCgojVHJpbSBsb29rdXAgdGFibGUgdG8gb25seSBpbmNsdWRlIHRob3NlIHdlIGhhdmUgZGF0YSBmb3IKdGVzdF93b3JrZXJfbG9va3VwIDwtIHRlc3Rfd29ya2VyX2xvb2t1cFt0ZXN0X3dvcmtlcl9sb29rdXAkc3ViX2lkICVpbiUgdGVzdF9kYXRhJHN1Yl9pZCxdCgojUmVwbGFjZSB3b3JrZXJfaWQncyBpbiByZXRlc3RfZGF0YSB3aXRoIG9yaWdpbmFsIHN1Yl9pZCdzIApjb3JyZWN0X3N1YmlkcyA8LSBmdW5jdGlvbihyb3csIGxvb2t1cF90YWJsZSl7CiAgc3ViX2lkID0gcm93JHN1Yl9pZAogIGlmKHN1Yl9pZCAlaW4lIGxvb2t1cF90YWJsZSR3b3JrZXJfaWQpewogICAgaW5kZXggPSB3aGljaChzdWJfaWQgPT0gbG9va3VwX3RhYmxlJHdvcmtlcl9pZCkKICAgIHN1Yl9pZCA9IGxvb2t1cF90YWJsZSRzdWJfaWRbaW5kZXhdCiAgICByb3ckc3ViX2lkID0gc3ViX2lkCiAgfQogIHJldHVybihyb3cpCn0KCnJldGVzdF9kYXRhIDwtIHJldGVzdF9kYXRhICU+JQogIGdyb3VwX2J5KHN1Yl9pZCkgJT4lCiAgZG8oY29ycmVjdF9zdWJpZHMoLix0ZXN0X3dvcmtlcl9sb29rdXApKQpgYGAKCkFyZSBhbGwgcmV0ZXN0IHN1YmplY3RzIGluIHRlc3RfZGF0YT8gTm8uIApgYGB7cn0Kc3VtKHJldGVzdF9kYXRhJHN1Yl9pZCAlaW4lIHRlc3RfZGF0YSRzdWJfaWQpID09IG5yb3cocmV0ZXN0X2RhdGEpCmBgYAoKV2hvIGlzIG1pc3Npbmc/CmBgYHtyfQpyZXRlc3RfZGF0YSRzdWJfaWRbd2hpY2gocmV0ZXN0X2RhdGEkc3ViX2lkICVpbiUgdGVzdF9kYXRhJHN1Yl9pZCA9PSBGQUxTRSldCmBgYAoKT25lIHJldGVzdCBwYXJ0aWNpcGFudCBpcyBub3QgaW4gdGVzdCBkYXRhLiBSZW1vdmUgdGhhdCBzdWJqZWN0IGZyb20gcmV0ZXN0X2RhdGEgZm9yIG5vdwpgYGB7cn0KcmV0ZXN0X2RhdGEgPC0gcmV0ZXN0X2RhdGFbcmV0ZXN0X2RhdGEkc3ViX2lkICVpbiUgdGVzdF9kYXRhJHN1Yl9pZCxdCgpyZXRlc3RfZGF0YQpgYGAKCkV4dHJhY3QgdGVzdCBkYXRhIGZvciByZXRlc3Qgc3ViamVjdHMKYGBge3J9CnJldGVzdF9zdWJzX3Rlc3RfZGF0YSA8LSB0ZXN0X2RhdGFbdGVzdF9kYXRhJHN1Yl9pZCAlaW4lIHJldGVzdF9kYXRhJHN1Yl9pZCxdCgpyZXN0X3N1YnNfdGVzdF9kYXRhIDwtIHRlc3RfZGF0YVt0ZXN0X2RhdGEkc3ViX2lkICVpbiUgcmV0ZXN0X2RhdGEkc3ViX2lkID09IEZBTFNFLF0KCiNBcnJhbmdlIGRhdGFzZXRzIG9mIHNhbWUgc2l6ZSBieSBzdWJfaWQKcmV0ZXN0X2RhdGEgPSByZXRlc3RfZGF0YSAlPiUgYXJyYW5nZShzdWJfaWQpCnJldGVzdF9zdWJzX3Rlc3RfZGF0YSA9IHJldGVzdF9zdWJzX3Rlc3RfZGF0YSAlPiUgYXJyYW5nZShzdWJfaWQpCgojQ0hFQ0sgSUYgRVZFUllUSElORyBJUyBPUkRFUkVEIFJJR0hUCnJldGVzdF9zdWJzX3Rlc3RfZGF0YSRzdWJfaWQgPT0gcmV0ZXN0X2RhdGEkc3ViX2lkCmBgYAoKRHJvcCBjb2x1bW5zIGZyb20gb3JpZ2luYWwgZGF0YSB0aGF0IGFyZSBub3QgaW4gcmV0ZXN0IGRhdGEKCkFyZSB0aGVyZSBhbnkgY29sdW1ucyBpbiByZXRlc3QgZGF0YSBjb2x1bW5zIHRoYXQgYXJlIG5vdCBpbiB0aGUgb3JpZ2luYWwgZGF0YTogTm8uCgpgYGB7cn0KbmFtZXMocmV0ZXN0X2RhdGEpW25hbWVzKHJldGVzdF9kYXRhKSAlaW4lIG5hbWVzKHJldGVzdF9zdWJzX3Rlc3RfZGF0YSkgPT0gRkFMU0VdCmBgYAoKVGVzdCBkYXRhIGNvbHVtbnMgdGhhdCBhcmUgbm90IGluIHRoZSByZXRlc3QgZGF0YTogVHdvIHN0YWdlIGhhc24ndCBiZWVuIGZpeGVkIHlldC4KCmBgYHtyfQpuYW1lcyhyZXRlc3Rfc3Vic190ZXN0X2RhdGEpW25hbWVzKHJldGVzdF9zdWJzX3Rlc3RfZGF0YSkgJWluJSBuYW1lcyhyZXRlc3RfZGF0YSkgPT0gRkFMU0VdCmBgYAoKRGF0YXNldHMgd2l0aCBvbmx5IG1hdGNoaW5nIGNvbHVtbnMKCmBgYHtyfQphbGxfY29sdW1ucyA8LSB1bmlxdWUoYyhuYW1lcyhyZXRlc3RfZGF0YSksIG5hbWVzKHJldGVzdF9zdWJzX3Rlc3RfZGF0YSkpKQoKbWF0Y2hpbmdfY29sdW1ucyA8LSBjKCkKZm9yKGkgaW4gMTpsZW5ndGgoYWxsX2NvbHVtbnMpKXsKICBpZihhbGxfY29sdW1uc1tpXSAlaW4lIG5hbWVzKHJldGVzdF9kYXRhKSAmIGFsbF9jb2x1bW5zW2ldICVpbiUgbmFtZXMocmV0ZXN0X3N1YnNfdGVzdF9kYXRhKSl7CiAgICBtYXRjaGluZ19jb2x1bW5zIDwtIGMobWF0Y2hpbmdfY29sdW1ucywgYWxsX2NvbHVtbnNbaV0pCiAgfQp9CgpyZXRlc3RfZGF0YSA8LSByZXRlc3RfZGF0YVssbWF0Y2hpbmdfY29sdW1uc10KcmV0ZXN0X3N1YnNfdGVzdF9kYXRhIDwtIHJldGVzdF9zdWJzX3Rlc3RfZGF0YVssbWF0Y2hpbmdfY29sdW1uc10KYGBgCgojIENvcnJlbGF0aW9ucyBvZiBleGhhdXN0aXZlIHZhcmlhYmxlcwoKR2V0IGxpc3Qgb2YgdGVzdCByZXRlc3QgY29ycmVsYXRpb25zIGZvciBhbGwgbWF0Y2hpbmcgKG51bWVyaWMpIGNvbHVtbnMgaW4gdGhlIHRlc3QgYW5kIHJldGVzdCBkYXRhLiBOb3RlIHR3byBjYXZlYXRzOgoxLiBUaGVyZSBhcmUgc3RpbGwgc29tZSBjb2x1bW5zIHRoYXQgd2VyZW4ndCBpbiBib3RoIGRhdGFzZXRzIChlLmcuIHR3byBzdGFnZSkKMi4gVW5saWtlIG1lYW5pbmdmdWwgdmFyaWFibGVzIHRoZXNlIHZhcmlhYmxlcyBhcmUgbm90ICh5ZXQpIHJpZCBvZiBvdXRsaWVycyBvciBsb2cgdHJhbnNmb3JtZWQgaWYgc2tld2VkLiBUaGlzIHdpbGwgYmUgZGV0YWlsZWQgYmVsb3cgYWxvbmcgd2l0aCBpdHMgcHJvYmxlbXMuCgpgYGB7cn0KcmV0ZXN0X2RhdGEgPC0gYXMuZGF0YS5mcmFtZShyZXRlc3RfZGF0YSkKcmV0ZXN0X3N1YnNfdGVzdF9kYXRhIDwtIGFzLmRhdGEuZnJhbWUocmV0ZXN0X3N1YnNfdGVzdF9kYXRhKQoKbWF0Y2hpbmdfZHZfY29sdW1ucyA8LSBjKCkKCmZvcihpIGluIDE6bGVuZ3RoKG1hdGNoaW5nX2NvbHVtbnMpKXsKICBpZihpcy5udW1lcmljKHJldGVzdF9kYXRhWyxtYXRjaGluZ19jb2x1bW5zW2ldXSkgJiBpcy5udW1lcmljKHJldGVzdF9zdWJzX3Rlc3RfZGF0YVssbWF0Y2hpbmdfY29sdW1uc1tpXV0pKXsKICAgIG1hdGNoaW5nX2R2X2NvbHVtbnMgPC0gYyhtYXRjaGluZ19kdl9jb2x1bW5zLCBtYXRjaGluZ19jb2x1bW5zW2ldKQogIH0KfQoKY29yX2RmIDwtIGRhdGEuZnJhbWUocGVhcnNvbiA9IHJlcChOQSwgbGVuZ3RoKG1hdGNoaW5nX2R2X2NvbHVtbnMpKSwgc3BlYXJtYW4gPSByZXAoTkEsIGxlbmd0aChtYXRjaGluZ19kdl9jb2x1bW5zKSkpCgpyb3cubmFtZXMoY29yX2RmKSA8LSBtYXRjaGluZ19kdl9jb2x1bW5zCgpmb3IoaSBpbiAxOmxlbmd0aChtYXRjaGluZ19kdl9jb2x1bW5zKSl7CiAgY29yX2RmW21hdGNoaW5nX2R2X2NvbHVtbnNbaV0sICdwZWFyc29uJ10gPC0gY29yKHJldGVzdF9kYXRhWyxtYXRjaGluZ19kdl9jb2x1bW5zW2ldXSwgcmV0ZXN0X3N1YnNfdGVzdF9kYXRhWyxtYXRjaGluZ19kdl9jb2x1bW5zW2ldXSwgbWV0aG9kID0gJ3BlYXJzb24nLCB1c2UgPSAicGFpcndpc2UuY29tcGxldGUub2JzIikKICBjb3JfZGZbbWF0Y2hpbmdfZHZfY29sdW1uc1tpXSwgJ3NwZWFybWFuJ10gPC0gY29yKHJldGVzdF9kYXRhWyxtYXRjaGluZ19kdl9jb2x1bW5zW2ldXSxyZXRlc3Rfc3Vic190ZXN0X2RhdGFbLG1hdGNoaW5nX2R2X2NvbHVtbnNbaV1dLCBtZXRob2QgPSAnc3BlYXJtYW4nLCB1c2UgPSAicGFpcndpc2UuY29tcGxldGUub2JzIikKfQpgYGAKCkRpc3RyaWJ1dGlvbiBvZiBhbGwgUGVhcnNvbiBhbmQgU3BlYXJtYW4gY29ycmVsYXRpb25zCmBgYHtyfQpjb3JfZGYgJT4lCiAgZ2F0aGVyKGtleSwgdmFsdWUpICU+JQogIGdncGxvdChhZXModmFsdWUpKSsKICBnZW9tX2hpc3RvZ3JhbSgpKwogIHRoZW1lX2J3KCkrCiAgZmFjZXRfd3JhcCh+a2V5KQpgYGAKCkFkZCBjb2x1bW4gdG8gdGFza3MgdnMuIHN1cnZleXMgaW4gY29ycmVsYXRpb24gdGFibGUKCmBgYHtyfQpjb3JfZGYkZHYgPSByb3cubmFtZXMoY29yX2RmKQpyb3cubmFtZXMoY29yX2RmKSA9IHNlcSgxOm5yb3coY29yX2RmKSkKY29yX2RmJHRhc2sgPSAndGFzaycKY29yX2RmW2dyZXAoJ3N1cnZleScsIGNvcl9kZiRkdiksICd0YXNrJ10gPSAnc3VydmV5JwpgYGAKCkRpc3RyaWJ1dGlvbnMgb2YgY29ycmVsYXRpb25zIGJ5IHRhc2sgdnMuIHN1cnZleQoKU3VydmV5IHJlbGlhYmlsaXRpZXMgYXJlIG5vdGljYWJseSBoaWdoZXIgdGhhbiB0YXNrIHJlbGlhYmlsaXRpZXMuCgpUYXNrIHJlbGlhYmlsaXR5IGRpc3RyaWJ1dGlvbnMgbG9va3MgYWxzbW9zdCBiaW1vZGFsLiAqKlNob3VsZCBmaWd1cmUgb3V0IHdoZXRoZXIgdGhlIGxvd2VyIG9uZXMgYXJlIHNwZWNpZmljIHRhc2tzIG9yIGlmIHRoZXkgYXJlIGNlcnRhaW4ga2luZHMgb2YgdmFycyAoZS5nLiBjZXJ0YWluIGRkbSBwYXJhbWV0ZXJzKSoqCmBgYHtyfQpjb3JfZGYgJT4lCiAgZ2F0aGVyKGtleSwgdmFsdWUsIC1kdiwgLXRhc2spICU+JQogIGdncGxvdChhZXModmFsdWUpKSsKICBnZW9tX2hpc3RvZ3JhbSgpKwogIHRoZW1lX2J3KCkrCiAgZmFjZXRfd3JhcChrZXl+dGFzaykKYGBgCgpSYW5rIG9yZGVyIGNvcnJlbGF0aW9ucwpGb3IgdGFza3MKYGBge3J9CmNvcl9kZiAlPiUKICBmaWx0ZXIodGFzayA9PSAndGFzaycpICU+JQogIHNlbGVjdChkdiwgc3BlYXJtYW4sIHBlYXJzb24pICU+JQogIGFycmFuZ2UoLXBlYXJzb24sIC1zcGVhcm1hbikKYGBgCgpNZWFuIHJlbGlhYmlsaXR5IGZvciB0YXNrcwpgYGB7cn0KY29yX2RmICU+JQogIGZpbHRlcih0YXNrID09ICd0YXNrJykgJT4lCiAgc2VsZWN0KGR2LCBzcGVhcm1hbiwgcGVhcnNvbikgJT4lCiAgYXJyYW5nZSgtcGVhcnNvbiwgLXNwZWFybWFuKSAlPiUKICBzdW1tYXJpc2UobWVhbl9wZWFyc29uID0gbWVhbihwZWFyc29uKSwKICAgICAgICAgICAgbWVhbl9zcGVhcm1hbiA9IG1lYW4oc3BlYXJtYW4pLAogICAgICAgICAgICBudW1fdmFycyA9IG4oKSkKYGBgCgpGb3Igc3VydmV5cwoKTm90ZTogSG9sdCBhbmQgTGF1cnkgdGVzdC1yZXRlc3QgaXMgcHJldHR5IHRlcnJpYmxlLiBJbiBwcmV2aW91cyBkYXRhIGl0IHdhcyB+LjM1LiBTaG91bGQgY2hlY2sgdG8gc2VlIGlmIHRoZXJlIGlzIGEgY29kaW5nIGVycm9yIHRoZXJlLgpgYGB7cn0KY29yX2RmICU+JQogIGZpbHRlcih0YXNrID09ICdzdXJ2ZXknKSAlPiUKICBzZWxlY3QoZHYsIHNwZWFybWFuLCBwZWFyc29uKSAlPiUKICBhcnJhbmdlKC1wZWFyc29uLCAtc3BlYXJtYW4pCmBgYAoKTWVhbiByZWxpYWJpbGl0eSBmb3Igc3VydmV5cwpgYGB7cn0KY29yX2RmICU+JQogIGZpbHRlcih0YXNrID09ICdzdXJ2ZXknKSAlPiUKICBzZWxlY3QoZHYsIHNwZWFybWFuLCBwZWFyc29uKSAlPiUKICBhcnJhbmdlKC1wZWFyc29uLCAtc3BlYXJtYW4pICU+JQogIHN1bW1hcmlzZShtZWFuX3BlYXJzb24gPSBtZWFuKHBlYXJzb24pLAogICAgICAgICAgICBtZWFuX3NwZWFybWFuID0gbWVhbihzcGVhcm1hbiksCiAgICAgICAgICAgIG51bV92YXJzID0gbigpKQpgYGAKCkRpc3RyaWJ1dGlvbiBvZiBlYWNoIHZhcmlhYmxlCgpDaGVjayBpZiB0aGUgdmFyaWFibGVzIHRoYXQgd2VudCBpbiB0byB0aGUgY29ycmVsYXRpb24gbWF0cml4IGhhdmUgbm9ybWFsIGRpc3RyaWJ1dGlvbnMgc2luY2UgYXQgbGVhc3QgdGhlIFBlYXJzb24gY29ycmVsYXRpb25zIGRlcGVuZCBvbiB0aGlzIGFzc3VtcHRpb24uIElmIG5vdCB0cmFuc2Zvcm0gZGF0YSBjb2x1bW5zIGluIGJvdGggcmV0ZXN0IGFuZCB0ZXN0IGRhdGEgYW5kIGNhbGN1bGF0ZSBhIG5ldyBjb3JyZWxhdGlvbiBkZi4KCkZ1bmN0aW9uIHRvIGNoZWNrIGlmIHRoZSB2YXJpYWJsZXMgdGhhdCB3ZW50IGluIHRvIGNvcl9kZiBoYXZlIG5vcm1hbCBkaXN0cmlidXRpb25zCmBgYHtyfQpkaWZmX2Zyb21fbm9ybWFsIDwtIGZ1bmN0aW9uKGNvbCl7CiAgcmV0dXJuKHNoYXBpcm8udGVzdChjb2wpJHAudmFsdWUgPCAwLjA1KQp9CmBgYAoKQ2hlY2sgZGlzdHJpYnV0aW9ucyBvZiByZXRlc3QgZGF0YQoKVGhlIHNtYWxsZXIgbWVhbmluZ2Z1bCB2YXJzIGRhdGFmcmFtZSBoYXZlIGJlZW4gc29tZXdoYXQgY2xlYW5lZC4gU28gZmFyIGluIHRoaXMgbm90ZWJvb2sgd2UgbG9va2VkIGF0IGFsbCB0aGUgdmFycyBpbiB0aGVpciByYXdlc3QgZm9ybS4gSGVyZSB3ZSdsbCBmaXJzdCBjaGVjayB0aGUgZGlzdHJpYnV0aW9ucyBvZiBhbGwgdGhlIHZhcmlhYmxlcyBhbmQgdGhlbiBhcHBseSB0aGUgc2FtZSBjbGVhbmluZyBwcm9jZWR1cmUgdGhhdCB3YXMgdXNlZCBmb3IgdGhlIG1lYW5pbmdmdWwgdmFyaWFibGVzIHRvIGFsbCBvZiB0aGVtLiAKCk5vdGUgdGhhdCBJJ20gZG9pbmcgdGhpcyBmb3IgdGhlIHNha2Ugb2YgY29uc2lzdGVuY3kgZm9yIG5vdy4gV2UgbWlnaHQgbGF0ZXIgZGVjaWRlIHRoYXQgd2Ugd291bGQgbGlrZSB0byB0cmFuc2Zvcm0gY2VydGFpbiB2YXJpYWJsZXMgb2YgaW50ZXJlc3QgaW4gb3RoZXIgd2F5cyB0byBiZSBhYmxlIHRvIGluY2x1ZGUgdGhlbSBpbiBvdXIgYW5hbHlzZXMgd2l0aG91dCB2aW9sYXRpbmcgdGhlIGFzc3VtcHRpb25zIG9mIHRob3NlIGFuYWx5c2VzLiBUaGUgY3VycmVudCBwcm9jZWR1cmUgY2hlY2tzIHRoZSBza2V3bmVzcyBvZiBhIGNvbHVtbgoKQ3JlYXRlIGFuZCBvcmdhbml6ZSBuZXcgZGYgd2hlcmUgZGlzdHJpYnV0aW9uIG9mIHZhcnMgZGF0YSBpcyBzdG9yZWQuIEZpcnN0IGZvciByZXRlc3QgZGF0YSBvbmx5OyB0aGVuIGZvciB0ZXN0IGRhdGEgZm9yIHN1YmplY3RzIHdobyBoYXZlIHJldGVzdCBkYXRhIC0gcmVzdHJpY3RpbmcgaGVyZSBzaW5jZSB0aGVzZSBhcmUgdGhlIHN1YnNldHMgb2YgZGF0YSB0aGF0IHdlbnQgaW4gdG8gdGhlIGNvcnJlbGF0aW9uIG1hdHJpeC4gTWVyZ2UgYW5kIGNsZWFudXAKYGBge3J9CmRpc3RfcmV0ZXN0X2RhdGEgPC0gYXMuZGF0YS5mcmFtZShhcHBseShyZXRlc3RfZGF0YVssbWF0Y2hpbmdfZHZfY29sdW1uc10sIDIsIGRpZmZfZnJvbV9ub3JtYWwpKQpuYW1lcyhkaXN0X3JldGVzdF9kYXRhKSA8LSBjKCdyZXRlc3Rfbm90X25vcm1hbCcpCmRpc3RfcmV0ZXN0X2RhdGEkZHYgPC0gcm93Lm5hbWVzKGRpc3RfcmV0ZXN0X2RhdGEpCnJvdy5uYW1lcyhkaXN0X3JldGVzdF9kYXRhKSA8LSBzZXEoMTpucm93KGRpc3RfcmV0ZXN0X2RhdGEpKQpkaXN0X3JldGVzdF9kYXRhID0gZGlzdF9yZXRlc3RfZGF0YSAlPiUgc2VsZWN0KGR2LCByZXRlc3Rfbm90X25vcm1hbCkKCmRpc3RfcmV0ZXN0X3N1YnNfdGVzdF9kYXRhIDwtIGFzLmRhdGEuZnJhbWUoYXBwbHkocmV0ZXN0X3N1YnNfdGVzdF9kYXRhWyxtYXRjaGluZ19kdl9jb2x1bW5zXSwgMiwgZGlmZl9mcm9tX25vcm1hbCkpCm5hbWVzKGRpc3RfcmV0ZXN0X3N1YnNfdGVzdF9kYXRhKSA8LSBjKCd0ZXN0X25vdF9ub3JtYWwnKQpkaXN0X3JldGVzdF9zdWJzX3Rlc3RfZGF0YSRkdiA8LSByb3cubmFtZXMoZGlzdF9yZXRlc3Rfc3Vic190ZXN0X2RhdGEpCnJvdy5uYW1lcyhkaXN0X3JldGVzdF9zdWJzX3Rlc3RfZGF0YSkgPC0gc2VxKDE6bnJvdyhkaXN0X3JldGVzdF9zdWJzX3Rlc3RfZGF0YSkpCmRpc3RfcmV0ZXN0X3N1YnNfdGVzdF9kYXRhID0gZGlzdF9yZXRlc3Rfc3Vic190ZXN0X2RhdGEgJT4lIHNlbGVjdChkdiwgdGVzdF9ub3Rfbm9ybWFsKQoKZGlzdF9kYXRhIDwtIG1lcmdlKGRpc3RfcmV0ZXN0X2RhdGEsIGRpc3RfcmV0ZXN0X3N1YnNfdGVzdF9kYXRhLCBieSA9ICdkdicpCgpybShkaXN0X3JldGVzdF9kYXRhLCBkaXN0X3JldGVzdF9zdWJzX3Rlc3RfZGF0YSkKYGBgCgpBZGQgd2hldGhlciBkdidzIGFyZSB0YXNrcyBvciBzdXJ2ZXkgdG8gZGlzdHJpYnV0aW9uIGRmcwpgYGB7cn0KZGlzdF9kYXRhID0gY29yX2RmICU+JQogIHNlbGVjdChkdiwgdGFzaykgJT4lCiAgbGVmdF9qb2luKGRpc3RfZGF0YSwgYnkgPSAnZHYnKQpgYGAKCldoYXQgcHJvcG9ydGlvbiBpcyBub3Qgbm9ybWFsPwpBIGxhcmdlIHByb3BvcnRpb24gb2YgdGhlIHZhcmlhYmxlcyBhcmUgbm90IG5vcm1hbCBmb3IgZGF0YSBmcm9tIGJvdGggc291cmNlcy4gTGFyZ2VyIHByb3BvcnRpb25zIG9mIHN1cnZleSBkYXRhIGFyZSBub3Qgbm9ybWFsIGNvbXBhcmVkIHRvIHRhc2sgZGF0YS4gCmBgYHtyfQpkaXN0X2RhdGEgJT4lCiAgZ3JvdXBfYnkodGFzaykgJT4lCiAgc3VtbWFyaXNlKG1lYW5fcmV0ZXN0X25vdF9ub3JtYWwgID0gbWVhbihyZXRlc3Rfbm90X25vcm1hbCksCiAgICAgICAgICAgIG1lYW5fdGVzdF9ub3Rfbm9ybWFsID0gbWVhbih0ZXN0X25vdF9ub3JtYWwpKQpgYGAKCkFyZSB0aGUgc2FtZSB2YXJzIHRoYXQgYXJlIG5vdCBub3JtYWxseSBkaXN0cmlidXRlZCBpbiB0aGUgcmV0ZXN0IGRhdGEgbm90IG5vcm1hbCBpbiB0ZXN0IGRhdGEgYXMgd2VsbD8KTGlzdCBvZiB2YXJpYWJsZXMgdGhhdCBoYXZlIGRpZmZlcmVudCBkaXN0cmlidXRpb25zIGluIHRoZSB0d28gdGltZSBwb2ludHMgKHNob3duIGhlcmUgaXMgd2hldGhlciB0aGV5IGFyZSBub3JtYWxseSBkaXN0cmlidXRlZCBpbiB0aGUgcmV0ZXN0IGRhdGEpCkEgbWFqb3JpdHkgb2YgdGhlbSBhcmUgZHJpZnQgZGlmZnVzaW9uIHBhcmFtZXRlcnMgKGJ1dCBub3RlIHRoYXQgdGhlc2UgdmFycyBhcmUgb3ZlcnJlcHJlc2VudGVkIHRvIGJlZ2luIHdpdGggLSBtb3JlIG9uIHRoZW0gbGF0ZXIpLgpgYGB7cn0KZGlzdF9kYXRhICU+JQogIGZpbHRlcihyZXRlc3Rfbm90X25vcm1hbCAhPSB0ZXN0X25vdF9ub3JtYWwpCmBgYAoKQXBwbHkgdGhlIHNhbWUgY2xlYW5pbmcgcHJvY2VkdXJlIHRoYXQgd2FzIHVzZWQgZm9yIG1lYW5pbmdmdWwgdmFycyBmb3IgYWxsIHZhcnM6CmBgYHtyfQpyZW1vdmVfb3V0bGllcnMgPSBmdW5jdGlvbihkYXRhX2NvbHVtbiwgcXVhbnRpbGVfcmFuZ2UgPSAyLjUpewogIAogIHFfMjUgPSBxdWFudGlsZShkYXRhX2NvbHVtbiwgbmEucm09VClbMl0KICBxXzUwID0gcXVhbnRpbGUoZGF0YV9jb2x1bW4sIG5hLnJtPVQpWzNdCiAgcV83NSA9IHF1YW50aWxlKGRhdGFfY29sdW1uLCBuYS5ybT1UKVs0XQogIAogIGxvd2xpbWl0ID0gcV81MCAtIHF1YW50aWxlX3JhbmdlKihxXzc1IC0gcV8yNSkKICBoaWdobGltaXQgPSBxXzUwICsgcXVhbnRpbGVfcmFuZ2UqKHFfNzUgLSBxXzI1KQogIAogIGRhdGFfY29sdW1uID0gaWZlbHNlKGRhdGFfY29sdW1uPGxvd2xpbWl0LCBOQSwgaWZlbHNlKGRhdGFfY29sdW1uPmhpZ2hsaW1pdCwgTkEsIGRhdGFfY29sdW1uKSkKICAKICByZXR1cm4oZGF0YV9jb2x1bW4pCn0KCiIldy9vJSIgPC0gZnVuY3Rpb24oeCwgeSkgeFsheCAlaW4lIHldCgpuZWdfbG9nIDwtIGZ1bmN0aW9uKGNvbHVtbil7CiAgY29sX21heCA9IG1heChjb2x1bW4sIG5hLnJtPVQpCiAgY29sdW1uID0gY29sX21heCsxLWNvbHVtbgogIHJldHVybihsb2coY29sdW1uKSkKfQoKdHJhbnNmb3JtX3JlbW92ZV9za2V3ID0gZnVuY3Rpb24oZGF0YSwgY29sdW1ucywgdGhyZXNob2xkID0gMSl7CiAgCiAgdG1wID0gYXMuZGF0YS5mcmFtZShhcHBseShkYXRhWyxjb2x1bW5zXSwyLHNrZXcpKQogIG5hbWVzKHRtcCkgPSBjKCJza2V3IikKICB0bXAkZHYgPSByb3cubmFtZXModG1wKQogIHRtcCA9IHRtcCAlPiUgCiAgICBmaWx0ZXIoYWJzKHNrZXcpPnRocmVzaG9sZCkKICAKICBza2V3ZWRfdmFyaWFibGVzID0gdG1wJGR2CiAgc2tld19zdWJzZXQgPSBkYXRhWywgc2tld2VkX3ZhcmlhYmxlc10KICBwb3NpdGl2ZV9zdWJzZXQgPSBkYXRhWyx0bXAkZHZbdG1wJHNrZXc+MF1dCiAgbmVnYXRpdmVfc3Vic2V0ID0gZGF0YVssdG1wJGR2W3RtcCRza2V3PDBdXQogIAogICMgdHJhbnNmb3JtIHZhcmlhYmxlcwogICMgbG9nIHRyYW5zZm9ybSBmb3IgcG9zaXRpdmUgc2tldwogIHBvc2l0aXZlX3N1YnNldCA9IGxvZyhwb3NpdGl2ZV9zdWJzZXQpCiAgc3VjY2Vzc2Z1bF90cmFuc2Zvcm1zID0gYXMuZGF0YS5mcmFtZShhcHBseShwb3NpdGl2ZV9zdWJzZXQsIDIsIHNrZXcpKQogIG5hbWVzKHN1Y2Nlc3NmdWxfdHJhbnNmb3JtcykgPSBjKCdza2V3JykKICBzdWNjZXNzZnVsX3RyYW5zZm9ybXMkZHYgPSByb3cubmFtZXMoc3VjY2Vzc2Z1bF90cmFuc2Zvcm1zKQogIHN1Y2Nlc3NmdWxfdHJhbnNmb3JtcyA9IHN1Y2Nlc3NmdWxfdHJhbnNmb3JtcyAlPiUgZmlsdGVyKGFicyhza2V3KTx0aHJlc2hvbGQpCiAgc3VjY2Vzc2Z1bF90cmFuc2Zvcm1zID0gc3VjY2Vzc2Z1bF90cmFuc2Zvcm1zJGR2CiAgc3VjY2Vzc2Z1bF90cmFuc2Zvcm1zID0gcG9zaXRpdmVfc3Vic2V0WyxzdWNjZXNzZnVsX3RyYW5zZm9ybXNdCiAgZHJvcHBlZF92YXJzID0gbmFtZXMocG9zaXRpdmVfc3Vic2V0KSAldy9vJSBuYW1lcyhzdWNjZXNzZnVsX3RyYW5zZm9ybXMpCiAgCiAgIyByZXBsYWNlIHRyYW5zZm9ybWVkIHZhcmlhYmxlcwogIGRhdGEgPSBkYXRhWywtYyh3aGljaChuYW1lcyhkYXRhKSAlaW4lIG5hbWVzKHBvc2l0aXZlX3N1YnNldCkpKV0KICBuYW1lcyhzdWNjZXNzZnVsX3RyYW5zZm9ybXMpID0gcGFzdGUwKG5hbWVzKHN1Y2Nlc3NmdWxfdHJhbnNmb3JtcyksICcubG9nVHInKQogIHByaW50Lm5vcXVvdGUocmVwKCcqJywgNDApKQogIHByaW50KHBhc3RlMCgnRHJvcHBpbmcgJywgbGVuZ3RoKGRyb3BwZWRfdmFycykgLCcgcG9zaXRpdmVseSBza2V3ZWQgZGF0YSB0aGF0IGNvdWxkIG5vdCBiZSB0cmFuc2Zvcm1lZCBzdWNjZXNzZnVsbHk6JykpCiAgcHJpbnQoZHJvcHBlZF92YXJzKQogIHByaW50Lm5vcXVvdGUocmVwKCcqJywgNDApKQogIGRhdGEgPSBjYmluZChkYXRhLCBzdWNjZXNzZnVsX3RyYW5zZm9ybXMpCiAgCiAgIyByZWZsZWN0ZWQgbG9nIHRyYW5zZm9ybSBmb3IgbmVnYXRpdmUgc2tldyAgICAgIAogIG5lZ2F0aXZlX3N1YnNldCA9IGFzLmRhdGEuZnJhbWUoYXBwbHkobmVnYXRpdmVfc3Vic2V0LCAyLCBuZWdfbG9nKSkKICBzdWNjZXNzZnVsX3RyYW5zZm9ybXMgPSBhcy5kYXRhLmZyYW1lKGFwcGx5KG5lZ2F0aXZlX3N1YnNldCwgMiwgc2tldykpCiAgbmFtZXMoc3VjY2Vzc2Z1bF90cmFuc2Zvcm1zKSA9IGMoJ3NrZXcnKQogIHN1Y2Nlc3NmdWxfdHJhbnNmb3JtcyRkdiA9IHJvdy5uYW1lcyhzdWNjZXNzZnVsX3RyYW5zZm9ybXMpCiAgc3VjY2Vzc2Z1bF90cmFuc2Zvcm1zID0gc3VjY2Vzc2Z1bF90cmFuc2Zvcm1zICU+JSBmaWx0ZXIoYWJzKHNrZXcpPDEpCiAgc3VjY2Vzc2Z1bF90cmFuc2Zvcm1zID0gc3VjY2Vzc2Z1bF90cmFuc2Zvcm1zJGR2CiAgc3VjY2Vzc2Z1bF90cmFuc2Zvcm1zID0gbmVnYXRpdmVfc3Vic2V0WyxzdWNjZXNzZnVsX3RyYW5zZm9ybXNdCiAgZHJvcHBlZF92YXJzID0gbmFtZXMobmVnYXRpdmVfc3Vic2V0KSAldy9vJSBuYW1lcyhzdWNjZXNzZnVsX3RyYW5zZm9ybXMpCiAgCiAgIyByZXBsYWNlIHRyYW5zZm9ybWVkIHZhcmlhYmxlcwogIGRhdGEgPSBkYXRhWywtYyh3aGljaChuYW1lcyhkYXRhKSAlaW4lIG5hbWVzKG5lZ2F0aXZlX3N1YnNldCkpKV0KICBuYW1lcyhzdWNjZXNzZnVsX3RyYW5zZm9ybXMpID0gcGFzdGUwKG5hbWVzKHN1Y2Nlc3NmdWxfdHJhbnNmb3JtcyksICcuUmVmbG9nVHInKQogIHByaW50Lm5vcXVvdGUocmVwKCcqJywgNDApKQogIHByaW50KHBhc3RlMCgnRHJvcHBpbmcgJywgbGVuZ3RoKGRyb3BwZWRfdmFycykgLCcgbmVnYXRpdmVseSBza2V3ZWQgZGF0YSB0aGF0IGNvdWxkIG5vdCBiZSB0cmFuc2Zvcm1lZCBzdWNjZXNzZnVsbHk6JykpCiAgcHJpbnQoZHJvcHBlZF92YXJzKQogIHByaW50Lm5vcXVvdGUocmVwKCcqJywgNDApKQogIGRhdGEgPSBjYmluZChkYXRhLCBzdWNjZXNzZnVsX3RyYW5zZm9ybXMpCiAgCiAgcmV0dXJuKGRhdGEpCn0KYGBgCgpgYGB7cn0KY2xlYW5fcmV0ZXN0X2RhdGEgPSBhcy5kYXRhLmZyYW1lKGFwcGx5KHJldGVzdF9kYXRhWywgbWF0Y2hpbmdfZHZfY29sdW1uc10sIDIsIHJlbW92ZV9vdXRsaWVycykpCmNsZWFuX3JldGVzdF9kYXRhID0gdHJhbnNmb3JtX3JlbW92ZV9za2V3KGNsZWFuX3JldGVzdF9kYXRhLCBtYXRjaGluZ19kdl9jb2x1bW5zKQpgYGAKCkknbSBub3Qgc3VyZSB3aGF0IGlzIHRoZSByaWdodCB0aGluZyB0byBkbyByZWdhcmRpbmcgdGhlIGNsZWFuaW5nIG9mIHRoZSB0ZXN0IGRhdGEgZm9yIHRoZSByZXRlc3Qgc3ViamVjdHMuIFNob3VsZCB0aGV5IGJlIGNsZWFuZWQgb24gdGhlIHdob2xlIHNhbXBsZSBmb3IgdGhlIHRpbWUgdGhleSB3ZXJlIGNvbGxlY3RlZCBvbiBhbmQgdGhlbiBleHRyYWN0ZWQgKHRoaXMgc2hvdWxkIGhhdmUgYW4gZWZmZWN0IG9uIG91dGxpZXJzIGFzIHdlbGwgYXMgdHJhbnNmb3JtYXRpb25zKSBvciBleHRyYWN0ZWQgYW5kIHRoZW4gY2xlYW5lZC4gSGVyZSBJIGFtIGRvaW5nIHRoZSBsYXR0ZXIgYnV0IHRoaXMgc2VlbXMgdG8gYmUgcmVzdWx0aW5nIGluIG1vcmUgc2tld2VkIHZhcmlhYmxlcy4KCmBgYHtyfQpjbGVhbl9yZXRlc3Rfc3Vic190ZXN0X2RhdGEgPSBhcy5kYXRhLmZyYW1lKGFwcGx5KHJldGVzdF9zdWJzX3Rlc3RfZGF0YVssIG1hdGNoaW5nX2R2X2NvbHVtbnNdLCAyLCByZW1vdmVfb3V0bGllcnMpKQpjbGVhbl9yZXRlc3Rfc3Vic190ZXN0X2RhdGEgPSB0cmFuc2Zvcm1fcmVtb3ZlX3NrZXcocmV0ZXN0X3N1YnNfdGVzdF9kYXRhLCBtYXRjaGluZ19kdl9jb2x1bW5zKQpgYGAKCkJ1dCB3aGF0IGFib3V0IGRyb3BwaW5nIGRpZmZlcmVudCB2YXJpYWJsZXMgZnJvbSB0aGUgdHdvIGRhdGFmcmFtZXMKCkRyaWZ0IGRpZmZ1c2lvbiB2YXJpYWJsZXM6IHJhdyB2YXJzIHZzLiBFWiB2cy4gaGRkbQoKTWVhbiByZWxpYWJpbGl0aWVzIGZvciBkaWZmZXJlbnQga2luZHMgb2YgdmFyaWFibGVzIChlLmcuIGRyaWZ0IHJhdGVzIGFuZCBORHM7IHNlcGFyYXRlbHkgZm9yIEVaIGFuZCBIRERNOyBzdWJ0cmFjdGlvbiB2cyBiYXNpYyB2YXJpYWJsZXMgLSBzaW5nbGUgdnMuIG11bHRpcGxlKQpgYGB7cn0KYGBgCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKQ2FuIHlvdSBnZXQgdGhlIGZhY3RvciBzdHJ1Y3R1cmUgZm9yIHRoZSByZXRlc3QKc3RlcCAxOlR0ZXN0IG9uIGFsbCBtZWFzdXJlcyBvZiBUMSBmb3IgcGVvcGxlIHcgYW5kIHdpdGhvdXQgcmV0ZXN0CmBgYHtyfQoKYGBgCgpzdGVwMiA6IGVmYSBvbiB0aGUgcGVvcGxlIHlvdSBkb24ndCBoYXZlIHJldGVzdCBvbiBhbmQgdGhlbiBwcmVkaWN0IGhvdyB3ZWxsIHRoaXMgaG9sZHMgdXAgZm9yIHBlb3BsZSB3IHJldGVzdCBvbiB0MSBhbmQgb24gdDIKCkRhdGEgY2xlYW5pbmcgZm9yIGVmYQpgYGB7cn0KI3JlYWQgaW4gb25seSBtZWFuaW5nZnVsIHZhcnMKbWVhbmluZ2Z1bF92YXJfdGVzdCA8LSByZWFkLmNzdignL1VzZXJzL3pleW5lcGVua2F2aS9Eb2N1bWVudHMvUG9sZHJhY2tMYWJMb2NhbC9TZWxmX1JlZ3VsYXRpb25fT250b2xvZ3kvRGF0YS9Db21wbGV0ZV8wMS0zMS0yMDE3L21lYW5pbmdmdWxfdmFyaWFibGVzX2NsZWFuLmNzdicpCgptZWFuaW5nZnVsX3Zhcl9yZXRlc3QgPC0gcmVhZC5jc3YoJy9Vc2Vycy96ZXluZXBlbmthdmkvRG9jdW1lbnRzL1BvbGRyYWNrTGFiTG9jYWwvU2VsZl9SZWd1bGF0aW9uX09udG9sb2d5L0RhdGEvUmV0ZXN0XzAyLTExLTIwMTcvbWVhbmluZ2Z1bF92YXJpYWJsZXNfY2xlYW4uY3N2JykKCiNQcm9jZXNzIHN1Yl9pZCBjb2x1bW5zIGluIHRoZSBkYXRhIGRhdGFmcmFtZXMKbWVhbmluZ2Z1bF92YXJfcmV0ZXN0JFggPC0gYXMuY2hhcmFjdGVyKG1lYW5pbmdmdWxfdmFyX3JldGVzdCRYKQptZWFuaW5nZnVsX3Zhcl90ZXN0JFggPC0gYXMuY2hhcmFjdGVyKG1lYW5pbmdmdWxfdmFyX3Rlc3QkWCkKCm5hbWVzKG1lYW5pbmdmdWxfdmFyX3JldGVzdClbMV0gPC0gJ3N1Yl9pZCcKbmFtZXMobWVhbmluZ2Z1bF92YXJfdGVzdClbMV0gPC0gJ3N1Yl9pZCcKCiNDbGVhbiBhbmQgc3Vic2V0IGRmcyBhcyBiZWZvcmUKbWVhbmluZ2Z1bF92YXJfcmV0ZXN0IDwtIG1lYW5pbmdmdWxfdmFyX3JldGVzdCAlPiUKICBncm91cF9ieShzdWJfaWQpICU+JQogIGRvKGNvcnJlY3Rfc3ViaWRzKC4sdGVzdF93b3JrZXJfbG9va3VwKSkKCiNBcmUgYWxsIHJldGVzdCBzdWJqZWN0cyBpbiB0ZXN0X2RhdGE/IE5vLiAKc3VtKG1lYW5pbmdmdWxfdmFyX3JldGVzdCRzdWJfaWQgJWluJSBtZWFuaW5nZnVsX3Zhcl90ZXN0JHN1Yl9pZCkgPT0gbnJvdyhtZWFuaW5nZnVsX3Zhcl9yZXRlc3QpCgojV2hvIGlzIG1pc3Npbmc/Cm1lYW5pbmdmdWxfdmFyX3JldGVzdCRzdWJfaWRbd2hpY2gobWVhbmluZ2Z1bF92YXJfcmV0ZXN0JHN1Yl9pZCAlaW4lIG1lYW5pbmdmdWxfdmFyX3Rlc3Qkc3ViX2lkID09IEZBTFNFKV0KCiNSZW1vdmUgc3ViIHcgbWlzc2luZyB0ZXN0IGRhdGEgZnJvbSByZXRlc3QgZGF0YQpyZXRlc3RfZGF0YV9tbmdmIDwtIG1lYW5pbmdmdWxfdmFyX3JldGVzdFttZWFuaW5nZnVsX3Zhcl9yZXRlc3Qkc3ViX2lkICVpbiUgbWVhbmluZ2Z1bF92YXJfdGVzdCRzdWJfaWQsXQoKI0V4dHJhY3QgdGVzdCBkYXRhIGZvciBzdWJzIHcgcmV0ZXN0IGRhdGEKcmV0ZXN0X3N1YnNfdGVzdF9tbmdmIDwtIG1lYW5pbmdmdWxfdmFyX3Rlc3RbbWVhbmluZ2Z1bF92YXJfdGVzdCRzdWJfaWQgJWluJSBtZWFuaW5nZnVsX3Zhcl9yZXRlc3Qkc3ViX2lkLF0KCiNFeHRyYWN0IHRlc3QgZGF0YSBmb3Igc3VicyB3aXRob3V0IHJldGVzdCBkYXRhIChlZmEgZGYpCnJlc3Rfc3Vic190ZXN0X21uZ2YgPC0gbWVhbmluZ2Z1bF92YXJfdGVzdFttZWFuaW5nZnVsX3Zhcl90ZXN0JHN1Yl9pZCAlaW4lIG1lYW5pbmdmdWxfdmFyX3JldGVzdCRzdWJfaWQgPT0gRkFMU0UsXQoKI0FycmFuZ2UgZGF0YXNldHMgb2Ygc2FtZSBzaXplIGJ5IHN1Yl9pZApyZXRlc3RfZGF0YV9tbmdmID0gcmV0ZXN0X2RhdGFfbW5nZiAlPiUgYXJyYW5nZShzdWJfaWQpCnJldGVzdF9zdWJzX3Rlc3RfbW5nZiA9IHJldGVzdF9zdWJzX3Rlc3RfbW5nZiAlPiUgYXJyYW5nZShzdWJfaWQpCgojQ0hFQ0sgSUYgRVZFUllUSElORyBJUyBPUkRFUkVEIFJJR0hUCnJldGVzdF9zdWJzX3Rlc3RfbW5nZiRzdWJfaWQgPT0gcmV0ZXN0X2RhdGFfbW5nZiRzdWJfaWQKYGBgCgpDaGVja2luZyBjb2x1bW5zIGZvciBlZmE6Ck5FRUQgVE8gUkVTT0xWRSBTT01FIERJRkZFUkVOQ0VTIElOIE1FQU5JTkdGVUwgVkFSUyBCRVRXRUVOIFRIRSBUV08gREFUQVNFVFMKYGBge3J9CiNDaGVjayBjb2x1bW5zIApuYW1lcyhyZXRlc3RfZGF0YV9tbmdmKVtuYW1lcyhyZXRlc3RfZGF0YV9tbmdmKSAlaW4lIG5hbWVzKHJldGVzdF9zdWJzX3Rlc3RfbW5nZikgPT0gRkFMU0VdCgpuYW1lcyhyZXRlc3Rfc3Vic190ZXN0X21uZ2YpW25hbWVzKHJldGVzdF9zdWJzX3Rlc3RfbW5nZikgJWluJSBuYW1lcyhyZXRlc3RfZGF0YV9tbmdmKSA9PSBGQUxTRV0KCiNTdWJzZXQgZGF0YXNldHMgd2l0aCBvbmx5IG1hdGNoaW5nIGNvbHVtbnMKYWxsX2NvbHVtbnNfbW5nZiA8LSB1bmlxdWUoYyhuYW1lcyhyZXRlc3RfZGF0YV9tbmdmKSwgbmFtZXMocmV0ZXN0X3N1YnNfdGVzdF9tbmdmKSkpCgptYXRjaGluZ19jb2x1bW5zX21uZ2YgPC0gYygpCmZvcihpIGluIDE6bGVuZ3RoKGFsbF9jb2x1bW5zX21uZ2YpKXsKICBpZihhbGxfY29sdW1uc19tbmdmW2ldICVpbiUgbmFtZXMocmV0ZXN0X2RhdGFfbW5nZikgJiBhbGxfY29sdW1uc19tbmdmW2ldICVpbiUgbmFtZXMocmV0ZXN0X3N1YnNfdGVzdF9tbmdmKSl7CiAgICBtYXRjaGluZ19jb2x1bW5zX21uZ2YgPC0gYyhtYXRjaGluZ19jb2x1bW5zX21uZ2YsIGFsbF9jb2x1bW5zX21uZ2ZbaV0pCiAgfQp9CgpyZXRlc3RfZGF0YV9tbmdmIDwtIHJldGVzdF9kYXRhX21uZ2ZbLG1hdGNoaW5nX2NvbHVtbnNfbW5nZl0KcmV0ZXN0X3N1YnNfdGVzdF9tbmdmIDwtIHJldGVzdF9zdWJzX3Rlc3RfbW5nZlssbWF0Y2hpbmdfY29sdW1uc19tbmdmXQpyZXN0X3N1YnNfdGVzdF9tbmdmIDwtIHJlc3Rfc3Vic190ZXN0X21uZ2ZbLG1hdGNoaW5nX2NvbHVtbnNfbW5nZl0KCiNzdGFuZGFyZGl6ZSBhbGwgdmFycyBnb2luZyBpbiB0byBmYWN0b3IgYW5hbHlzaXMKcmVzdF9zdWJzX3Rlc3RfbW5nZl96IDwtIHJlc3Rfc3Vic190ZXN0X21uZ2YKCmZvcihpIGluIDE6bGVuZ3RoKHJlc3Rfc3Vic190ZXN0X21uZ2YpKXsKICBpZihuYW1lcyhyZXN0X3N1YnNfdGVzdF9tbmdmKVtpXSA9PSAnc3ViX2lkJyl7CiAgICByZXN0X3N1YnNfdGVzdF9tbmdmX3okc3ViX2lkID0gcmVzdF9zdWJzX3Rlc3RfbW5nZiRzdWJfaWQKICB9CiAgZWxzZXsKICAgIHJlc3Rfc3Vic190ZXN0X21uZ2ZfelssbmFtZXMocmVzdF9zdWJzX3Rlc3RfbW5nZilbaV1dID0gc2NhbGUocmVzdF9zdWJzX3Rlc3RfbW5nZlssaV0pCiAgfQp9CgpyZXN0X3N1YnNfdGVzdF9tbmdmX3ogPC0gYXMuZGF0YS5mcmFtZShyZXN0X3N1YnNfdGVzdF9tbmdmX3opCmBgYAoKCkVmYSBvbiBzdWJqZWN0cyBmcm9tIG9yaWdpbmFsIGRhdGFzZXQgd2l0aE9VVCByZXRlc3QgZGF0YSAodXNpbmcgbWVhbmluZ2Z1bCB2YXJzIG9ubHkpCmBgYHtyfQp1bnJvdGF0ZWQgPC0gZWZhVW5yb3RhdGUocmVzdF9zdWJzX3Rlc3RfbW5nZl96LCBuZj0zLCB2YXJMaXN0PW5hbWVzKHJlc3Rfc3Vic190ZXN0X21uZ2ZfeilbLTFdLCBlc3RpbWF0b3I9Im1sciIpCgpzdW1tYXJ5KHVucm90YXRlZCwgc3RkPVRSVUUpCmluc3BlY3QodW5yb3RhdGVkLCAic3RkIikKYGBgCgoKYGBge3J9CmNvck1hdCA8LSByZXN0X3N1YnNfdGVzdF9tbmdmX3ogJT4lIHNlbGVjdCgtc3ViX2lkKSAlPiUgY29yKC4sdXNlID0gJ2NvbXBsZXRlLm9icycpCgpzb2x1dGlvbiA8LSBmYShyID0gY29yTWF0LCBuZmFjdG9ycyA9IDMsIHJvdGF0ZSA9ICJvYmxpbWluIiwgZm0gPSAicGEiKQpgYGAKCmBgYHtyfQpzb2x1dGlvbgpgYGAKCiAKQ29tcGxldGlvbiB0aW1lcy9kYXlzCiAKIC0gRmlyc3QgZGF0YSByZWxlYXNlIGVtYWlsIGVzcCB0byBBU1UKIC0gU2VuZCB0aGUgc3ByZWFkc2hlZXQgd2l0aCBtZWFuaW5ndWwgdmFyaWFibGVzICsgZGVtb2dyYXBoaWNzCiAKIApUMSBjb21wYXJpc29uIGZvciBwZW9wbGUgd2hvIGNhbWUgYmFjayB2cyBkaWRuJ3QgKG9mIGFsbCB0aGF0IGFyZSBpbnZpdGVkKQo=